/*
  Programa Wifis, 2010-2011
  Autor: Nilhcraiv

This file is part of Wifis.

    Wifis is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Wifis is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Wifis.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <QProcess>
#include <QMessageBox>
#include <QByteArray>
#include <QDebug>
#include <QDir>

#include "windowsos.h"
#include "mainwindow.h"
#include "passwords.h"

windowsos::windowsos(QObject *parent)
    : QThread(parent)
{
}

windowsos::~windowsos()
{
}

//Protected functions
void windowsos::run()//Reimplemento run()
{
    //Variables
    QProcess detectProcess;
    QByteArray textNetworks;
    QString tempSSID,tempTypeNetwork,tempAutnetwork,tempEncryption,
            tempBSSID,tempSignal,tempRadio,tempChannel;

    passwords a;

    vectorNetworks.clear();//Lo inicializo.

    //first I use the command of the windows system for to detection neetworks
    detectProcess.start("cmd.exe /C netsh wlan show network mode=BSSID",QIODevice::ReadOnly);

    if (detectProcess.waitForStarted() == false) {
        qDebug() << "Error to detect neetworks";
        return;
    }//if

    detectProcess.waitForReadyRead();
    detectProcess.waitForFinished();
    textNetworks = detectProcess.readAllStandardOutput();
    detectProcess.close();

    bool heTermindao=false; int posicion = 0;
    while(!heTermindao)
    {
        //Detectar SSID
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\nSSID ",posicion)==-1){
                posicion++;
                heTermindao=true;
            }
            else{
                heTermindao=false;
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'
        if(heTermindao)
            break;

        if(posicion==textNetworks.size())
            break;

        textNetworks.remove(0,posicion+6);//Porque "\nSSID " tiene 6 caracteres
        posicion = 0;

        //Detectar Tipo de Red
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempSSID = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar autentificacion
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempTypeNetwork = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar Cifrado
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempAutnetwork = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar BSSID
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempEncryption = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar Señal
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempBSSID = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar Tipo de radio
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempSignal = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar Canal
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempRadio = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        //Detectar BSSID
        while(posicion<textNetworks.size())
        {
            if(textNetworks.lastIndexOf("\n ",posicion)==-1){
                posicion++;}
            else{
                break;
            }
        }//Al salir me encuentro en la posicion del caracter de '\n'

        tempChannel = textNetworks.mid(0,posicion);
        textNetworks.remove(0,posicion+2);//Porque "\n " tiene 2 caracteres
        posicion = 0;

        if(!this->checkParametro(&tempSSID))
            break;
        if(!this->checkBSSID(&tempBSSID))
            break;
        if(!this->checkParametro(&tempTypeNetwork))
            break;
        if(!this->checkParametro(&tempAutnetwork))
            break;
        if(!this->checkParametro(&tempEncryption))
            break;
        if(!this->checkParametro(&tempSignal))
            break;
        if(!this->checkParametro(&tempRadio))
            break;
        if(!this->checkParametro(&tempChannel))
            break;

        vectorNetworks.push_back(tempSSID);
        vectorNetworks.push_back(tempTypeNetwork);
        vectorNetworks.push_back(tempAutnetwork);
        vectorNetworks.push_back(tempEncryption);
        vectorNetworks.push_back(tempBSSID);
        vectorNetworks.push_back(tempSignal);
        vectorNetworks.push_back(tempRadio);
        vectorNetworks.push_back(tempChannel);
        vectorNetworks.push_back(a.getPassword(tempSSID,tempBSSID,tempEncryption,tempAutnetwork).at(1));
        vectorNetworks.push_back(a.getPassword(tempSSID,tempBSSID,tempEncryption,tempAutnetwork).at(0));
        tempSSID.clear(); tempTypeNetwork.clear();tempAutnetwork.clear();tempEncryption.clear();
        tempBSSID.clear();tempSignal.clear();tempRadio.clear();tempChannel.clear();
    }

    if(!heTermindao)
    {
        qDebug() << "ERROR AL DETECTAR REDES";
        vectorNetworks.clear();
    }
}//searchNetworks

void windowsos::connectToNetwork(QString SSID, QString password)
{
    QString text,text2,text3,text4,perfil = QDir::homePath().append("\\.conexion.xml");

    if(password.startsWith("CLAVE NO FIABLE AL 100% -> "))
        password.remove(0,27);

    //Open the file for writing, and set the text stream to write, to the file.
    QFile file_for_writing(perfil);
    file_for_writing.open(QIODevice::WriteOnly | QIODevice::Truncate); //
    QTextStream text_stream_for_writing(&file_for_writing);
    //set the text of the file
    text = "<?xml version=\"1.0\"?>\n<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">\n<name>Wifis</name>\n<SSIDConfig>\n<SSID>";
    text2 = "\n<name>";
    text3 = "</name>\n</SSID>\n</SSIDConfig>\n<connectionType>ESS</connectionType>\n<connectionMode>auto</connectionMode>\n<MSM>\n<security>\n<authEncryption>\n<authentication>WPAPSK</authentication>\n<encryption>TKIP</encryption>\n<useOneX>false</useOneX>\n</authEncryption>\n<sharedKey>\n<keyType>passPhrase</keyType>\n<protected>false</protected>\n<keyMaterial>";
    text4="</keyMaterial>\n</sharedKey>\n</security>\n</MSM>\n</WLANProfile>";
    text_stream_for_writing << text;
    text_stream_for_writing << text2;
    text_stream_for_writing << SSID;
    text_stream_for_writing << text3;
    text_stream_for_writing << password;
    text_stream_for_writing << text4;
    //close the file
    file_for_writing.close();
    //empty the text.
    text.clear();

    QProcess::execute("netsh wlan del profile Wifis");//Borro el perfil de la conexión si la ubiese

    QString comando;
    comando.append("cmd.exe /C netsh wlan add profile filename=");
    comando.append(perfil);
    QProcess::execute(comando);
    comando.clear();
    comando.append("cmd.exe /C netsh wlan connect name=\"Wifis\"");
    QProcess::execute(comando);
    comando.clear();

    QFile::remove(perfil);
}

bool windowsos::checkBSSID(QString *bssid)
{
    int check = 0; char caracteres[ ] = "0123456789abcdef:";

    *bssid = bssid->right(18).trimmed();

    if(bssid->size()!=17)
        return false;

    for(int i=0; i<bssid->size();i++)
    {
        for(int j =0; j<17; j++)
        {
            if(bssid->at(i) == caracteres[j])
                check++;
        }//for j
    }//for i

    if(check!=17)
        return false;

    return true;
}//checkBSSID

bool windowsos::checkParametro(QString *parametro)
{
    bool finished = false; int i = 0;

    while(!finished || i >= parametro->size())
    {
        if(parametro->at(i) == ':')
            finished = true;
        i++;
    }

    if(!finished)
        return false;

    parametro->remove(0,i);
    *parametro = parametro->trimmed();

    return true;
}//checkParametro
